package org.vectrics.recruiter.struts.admin;

import java.util.Collection;

import javax.servlet.jsp.JspException;

import org.apache.log4j.Category;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.vectrics.SystemException;
import org.vectrics.common.db.ExpirableUtils;
import org.vectrics.common.util.StringUtils;
import org.vectrics.domain.Domain;
import org.vectrics.hibernate.HibernateUtil;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.recruiter.RecruitDisplayUtils;
import org.vectrics.recruiter.RecruitServiceLocator;
import org.vectrics.recruiter.job.Job;
import org.vectrics.recruiter.job.JobCandidate;
import org.vectrics.recruiter.job.JobCandidateStatusReasonType;
import org.vectrics.recruiter.job.JobCandidateStatusType;
import org.vectrics.recruiter.job.JobStatus;
import org.vectrics.recruiter.job.JobStatusReasonType;
import org.vectrics.recruiter.job.JobStatusType;
import org.vectrics.recruiter.user.Resume;
import org.vectrics.struts.VectricsActionData;
import org.vectrics.struts.VectricsStrutsAction;

public class SaveJobCandidateAction extends VectricsStrutsAction {
    private static Category log = Category.getInstance(SaveJobCandidateAction.class);

    /**
     * Save the the candidate information entered by the user and determine if
     * another form will be displayed to the user to select a reason for the
     * status change.
     */
    @Override
    public String doExecute(final VectricsActionData actionData) throws JspException {
        log.debug("doExecute() called");
        String forward = "success";
        Domain domain = ThreadProperties.getDomain();
        if (actionData.wasButtonPressed("cancel"))
            return "cancel";
        else {
            JobCandidateForm form = (JobCandidateForm) actionData.getForm();
            String jobCandidateId = form.getJobCandidateId();
            JobCandidate jobCandidate = RecruitServiceLocator.getJobProvider().findJobCandidateById(
                    new Long(jobCandidateId));

            // String fromStatusCode = null;
            if (actionData.wasButtonPressed("button.yes.close.job")) {
                ThreadProperties.forcedCommitAndNewTransaction();
                jobCandidate = RecruitServiceLocator.getJobProvider().findJobCandidateById(new Long(jobCandidateId));
                Job job = jobCandidate.getJob();
                JobStatus jobStatus = jobCandidate.getJob().getCurrentStatus();
                JobStatusReasonType reasonType = RecruitServiceLocator.getJobProvider().findDefaultStatusReason(
                        job.getDomain(), jobStatus.getStatusType().getCode(), JobStatusType.STATUS_FILLED);

                HibernateUtil hibernate = (HibernateUtil) CoreServiceLocator.findServiceBean("hibernate.util");
                Session s = hibernate.createNewSession();
                Transaction t = s.beginTransaction();
                job = (Job) s.load(Job.class, job.getId());
                job.setStatus(
                        RecruitServiceLocator.getJobProvider().findJobStatusType(JobStatusType.STATUS_FILLED,
                                job.getDomain()), actionData.getAuthPerson(), reasonType);

                s.update(job);
                s.flush();
                t.commit();
                s.close();

                // HibernateSessionStore.forcedCommitAndNewSession();

            } else {

                if (form.getStatusCode() == null)
                    throw new SystemException("Status code is null");

                JobCandidateStatusType oldStatusType = jobCandidate.getCurrentStatus().getStatusType();
                JobCandidateStatusType newStatusType = RecruitServiceLocator.getJobProvider()
                        .findJobCandidateStatusType(form.getStatusCode());

                if (newStatusType.getCode().equals("hired")) {
                    if (jobCandidate.getJob() != null && jobCandidate.getJob().getFunction() != null) {
                        form.setFunction(jobCandidate.getJob().getFunction().getCode());
                        actionData.getRequest().setAttribute("function", form.getFunction());
                    }
                    if (jobCandidate.getJob() != null && jobCandidate.getJob().getLocation() != null) {
                        form.setLocation(jobCandidate.getJob().getLocation().getId().toString());
                        actionData.getRequest().setAttribute("location",
                                jobCandidate.getJob().getLocation().getId().toString());
                    }
                    if (jobCandidate.getJob() != null) {
                        actionData.getRequest().setAttribute("jobId", jobCandidate.getJob().getId().toString());
                    }
                    if (!StringUtils.isNullOrBlank(form.getNote())) {
                        actionData.getRequest().setAttribute("hiredNote", form.getNote());
                    }
                    return "hired";
                }

                log.info("For now, use default reason for status change, may need to ask user "
                        + "later to select a reason if more than 1 are configured for status change.");
                JobCandidateStatusReasonType defaultStatusReason = RecruitServiceLocator.getJobProvider()
                        .findDefaultCandidateStatusReason(domain, oldStatusType.getCode(), newStatusType.getCode());

                jobCandidate.setStatus(newStatusType.getCode(), defaultStatusReason, actionData.getAuthPerson());
                jobCandidate.setStrength(new Long(form.getStrength()));
                jobCandidate.setNote(form.getNote());
                if (StringUtils.isNullOrBlank(form.getResumeId()) || form.getResumeId().equals("0")) {
                    jobCandidate.setResume(null);
                } else {
                    Long resumeId = new Long(form.getResumeId());
                    Resume resume = RecruitServiceLocator.getRecruitUserService().findResume(resumeId);
                    jobCandidate.setResume(resume);
                }
                RecruitServiceLocator.getJobProvider().updateJobCandidate(jobCandidate);
                ExpirableUtils.validateNoGaps(jobCandidate.getStatusList());
                ExpirableUtils.validateNoGapsNoEnd(jobCandidate.getStatusList());
                RecruitServiceLocator.getJobProvider().updateJob(jobCandidate.getJob());
                ThreadProperties.forcedCommit();

                form.setStatusDescription(jobCandidate.getCurrentStatus().getStatusType().getDescription());
                actionData.setRequestForm(form);

                Collection possibleReasonsForStatusChange = RecruitServiceLocator.getJobProvider()
                        .findJobCandidateStatusReasonTypes(domain, oldStatusType.getCode(), newStatusType.getCode());
                log.info("possibleReasonsForStatusChange.size = " + possibleReasonsForStatusChange.size());
                if (possibleReasonsForStatusChange.size() > 1) {
                    log.info("There are more than 1 possible reasons for status change, we need to ask the user which reason to use.");
                    forward = "need.reason";

                    log.info("Attach the collection to a request attribute to be used in a selection on the next form");
                    Collection reasons = RecruitDisplayUtils.jobCandidateReasonTypesToCoded(
                            possibleReasonsForStatusChange, actionData.getLocale());

                    actionData.getRequest().setAttribute("reasons", reasons);
                } else {
                    log.info("Configuration only has 1 reason for status change, use it and don't bother the user");
                    /*
                     * if
                     * ((newStatusType.getCode().equals(JobCandidateStatusType
                     * .STATUS_CANDIDATE_HIRED)) &&
                     * (!newStatusType.getCode().equals(oldStatusType.getCode())
                     * &&
                     * (jobCandidate.getJob().getCurrentStatus().getStatusType
                     * ().getCode().equals(JobStatusType.STATUS_FILLED) ==
                     * false))) { // Candidate was hired, see if user wishes to
                     * close the job
                     * form.setCandidateName(jobCandidate.getCandidate
                     * ().getPerson().getName());
                     * form.setJobTitle(jobCandidate.getJob().getTitle());
                     * forward = "close.job.hired"; }
                     */
                }
                actionData.getRequest().setAttribute("jobCandidateId", jobCandidate.getId());
            }
        }

        return forward;

    }

}
